/**
 * Bakalarska prace - Inteligentni budik
 * @package sleepCatcher
 * @file SCSleepView.h
 * @author Jan Pesava - xpesav00
 * @email xpesav00@stud.fit.vutbr.cz
 * @date 12. 3. 2012
 */

#include "models/SCSleepView.h"
#include "forms/FormCatchSleep.h"
#include "SCFormManager.h"

SCSleepView::SCSleepView(Form* pCurrentForm, int x, int y, int width, int height, int countOfSamples, int simpleAvarage)
{
	this->x = x;
	this->y = y;
	this->height = height;
	this->width = width;
	this->countOfSamples = countOfSamples;
	this->simpleAvarage = simpleAvarage;
	this->pCurrentForm = pCurrentForm;
	this->i = 0;

	this->pWindowEnergy = new Queue();
	this->pWindow = new Queue();
	this->energySum = 0;
	this->maxY = 0;
	this->minY = 0;

	this->pSleepViewGraph = new Canvas();
	this->pSleepViewGraph->Construct(Rectangle(this->x, this->y, this->width, this->height));

	//set background
	Image *pImage = new Image();
	pImage->Construct();
	this->pBitmapBG = pImage->DecodeN("/Home/Icons/Commons/cityscape_night_480x616.png", BITMAP_PIXEL_FORMAT_RGB565);

	this->Init();

	delete pImage;
}

SCSleepView::SCSleepView(Form* pCurrentForm, int x, int y, int width, int height, SCSession* pSession)
{
	// Not Implementerd
}

SCSleepView::~SCSleepView()
{
	this->pWindow->RemoveAll(true);
	this->pWindowEnergy->RemoveAll(true);

	delete this->pSleepViewGraph;
	delete this->pWindow;
	delete this->pWindowEnergy;
	delete pBitmapBG;
}


void
SCSleepView::Init()
{
	this->pWindowEnergy->RemoveAll(true);
	this->pWindow->RemoveAll(true);
	this->energySum = 0;
	this->maxY = 0;
	this->minY = 0;
	this->margin = 0;
}

void
SCSleepView::SetX(int value)
{
	this->x = value;
}

int
SCSleepView::GetX()
{
	return this->x;
}

void
SCSleepView::SetY(int value)
{
	this->y = value;
}

int
SCSleepView::GetY()
{
	return this->y;
}

void
SCSleepView::SetMinY(float value)
{
	this->minY = value;
}

int
SCSleepView::GetMinY()
{
	return this->minY;
}

void
SCSleepView::SetMaxY(float value)
{
	this->maxY = value;
}

int
SCSleepView::GetMaxY()
{
	return this->maxY;
}

void
SCSleepView::SetHeight(int value)
{
	this->height = value;
}

int
SCSleepView::GetHeight()
{
	return this->height;
}

void
SCSleepView::SetWidth(int value)
{
	this->width = value;
}

int
SCSleepView::GetWidth()
{
	return this->width;
}

void
SCSleepView::SetCountOfSamples(int value)
{
	this->countOfSamples = value;
}

int
SCSleepView::GetCountOfSamples()
{
	return this->countOfSamples;
}

void
SCSleepView::SetSleepViewGraph(Canvas* pCanvas)
{
	this->pSleepViewGraph = pCanvas;
}

Canvas*
SCSleepView::GetSleepViewGraph()
{
	return this->pSleepViewGraph;
}

void
SCSleepView::SetSession(SCSession* pSession)
{
	this->pSession = pSession;
}

SCSession*
SCSleepView::GetSession()
{
	return this->pSession;
}

void
SCSleepView::AddSample(SCSample* pSample)
{
	//declaration
	Float* pRemoveFloat;
	Float* pFloat = new Float();

	//set and add to frame
	if(this->pWindowEnergy->GetCount() < this->countOfSamples)
	{
		this->pWindowEnergy->Enqueue(*pFloat);
	} else {
		pRemoveFloat = static_cast<Float*>(this->pWindowEnergy->Dequeue());
		delete pRemoveFloat;
		this->pWindowEnergy->Enqueue(*pFloat);
	}

	//set WindowEnergy
	*pFloat = this->ComputeWindowEnergy(pSample);

	//set Extremes
	this->SetExtemes(pFloat);

	//redraw
	if(!SCFormManager::appOnBackground && !SCFormManager::screenSaver)
	{
		this->Redraw();
	} else {
		// Not Implemented
	}

	//dealloc
	delete pSample;
}

float
SCSleepView::ComputeWindowEnergy(SCSample* pAddedSample)
{
	if(this->pWindow->GetCount() < this->simpleAvarage)
	{
		this->energySum += pAddedSample->GetEnergy();
		this->pWindow->Enqueue(*(new Float(pAddedSample->GetEnergy())));
	} else {
		Float* removeEnergy = static_cast<Float*>(this->pWindow->Dequeue());
		this->energySum += pAddedSample->GetEnergy() - removeEnergy->ToFloat();
		this->pWindow->Enqueue(*(new Float(pAddedSample->GetEnergy())));

		delete removeEnergy;
	}

	return this->energySum / this->pWindow->GetCount();
}

void
SCSleepView::SetExtemes(Float* pLastEnergy)
{
	//set MaxY
	if(this->maxY < pLastEnergy->ToFloat())
	{
		this->maxY = pLastEnergy->ToFloat();
	}

	//set MinY
	if(this->minY > pLastEnergy->ToFloat())
	{
		this->minY = pLastEnergy->ToFloat();
	}
}

Bitmap*
SCSleepView::CreatePicture()
{
	Bitmap* pBitmap = null;

	return pBitmap;
}

void
SCSleepView::SetDefaultValues()
{
	this->maxY = 0;
	this->minY = 0;
	this->margin = 0;
}

void
SCSleepView::InitSleepViewGraph()
{
	this->pSleepViewGraph->SetLineStyle(LINE_STYLE_SOLID);
	this->pSleepViewGraph->SetLineWidth(5);
	this->pSleepViewGraph->SetForegroundColor(Color::COLOR_WHITE);
	this->pSleepViewGraph->DrawLine(Point(margin, 0), Point(this->margin, this->height - (this->margin/2)));
	this->pSleepViewGraph->DrawLine(Point(this->margin/2, this->height - margin), Point(this->width, this->height-margin));
	this->pSleepViewGraph->DrawText(Point(this->width/2, this->height-margin + 5), "Time");

	//Set Titles
	Bitmap* pBitmap = new Bitmap();
	Canvas* pCanvasTmp = new Canvas();
	pCanvasTmp->Construct(Rectangle(0, 0, 100, 30));
	pCanvasTmp->DrawText(Point(0,0), "Light sleep");
	pBitmap->Construct(*pCanvasTmp, pCanvasTmp->GetBounds());

	Bitmap* pBitmap2 = new Bitmap();
	Canvas* pCanvasTmp2 = new Canvas();
	pCanvasTmp2->Construct(Rectangle(0, 0, 100, 30));
	pCanvasTmp2->DrawText(Point(0,0), "Deep sleep");
	pBitmap2->Construct(*pCanvasTmp2, pCanvasTmp2->GetBounds());

	this->pSleepViewGraph->DrawBitmap(Point(10,100), *pBitmap, Point(0,0), 90);
	this->pSleepViewGraph->DrawBitmap(Point(10,550), *pBitmap2, Point(0,0), 90);
}

void
SCSleepView::Update()
{
	// Not implemented
}

void
SCSleepView::Redraw()
{
	this->pSleepViewGraph->Clear();

	//init axis
	//this->InitSleepViewGraph();

	//getPoints
	IList* pPointsList = this->CreatePointListN(this->width, this->height);

	// set params
	this->pSleepViewGraph->SetLineWidth(3);
	this->pSleepViewGraph->SetForegroundColor(Color::COLOR_WHITE);

	//drawAndFill
	this->pSleepViewGraph->DrawBitmap(Point(0,0), *this->pBitmapBG);
	this->pSleepViewGraph->FillPolygon(Color::COLOR_CYAN, *pPointsList);
	this->pSleepViewGraph->DrawPolygon(*pPointsList);

	// show canvas
	if(!SCFormManager::appOnBackground && !SCFormManager::screenSaver)
	{
		this->pSleepViewGraph->Show();
	}

	//dealloc
	pPointsList->RemoveAll(true);
	delete pPointsList;
}

Osp::Base::Collection::IList*
SCSleepView::CreatePointListN(int width, int height)
{
	IList* pPointList = new ArrayList();

	if(this->pWindowEnergy->GetCount() > 0)
	{
		Float* pFloat;
		float maxY = this->maxY;
		int x, y;
		float differenceX, differenceY;
		int position = 0;

		//set difference
		differenceX = (float)width / this->countOfSamples;
		if(maxY == 0)
			differenceY = 0;
		else
			differenceY = (float)height / maxY;

		//create Enumerator
		IEnumerator* pEnum = this->pWindowEnergy->GetEnumeratorN();

		//set offset
		if(this->pWindowEnergy->GetCount() < this->countOfSamples)
		{
			position = this->countOfSamples - this->pWindowEnergy->GetCount();
		}

		//create points
		pPointList->Add(*(new Point(position * differenceX, this->height)));
		while(pEnum->MoveNext() == E_SUCCESS)
		{
			pFloat = static_cast<Float*>(pEnum->GetCurrent());
			x = position * differenceX;
			y = height - pFloat->ToFloat() * differenceY;

			//add point
			pPointList->Add(*(new Point(x,y)));
			position++;
		}
		pPointList->Add(*(new Point(width, height)));

		delete pEnum;
	}

	return pPointList;
}


void
SCSleepView::StartCatch()
{
	this->Init();
}

void
SCSleepView::StopCatch()
{
	this->pWindow->RemoveAll(true);
	this->pWindowEnergy->RemoveAll(true);
}

